package cn.net.autocode.platform.providers;

import cn.hutool.core.util.StrUtil;
import cn.net.autocode.platform.config.SpringProfileConfig;
import cn.net.autocode.platform.exception.PlatformQueryException;
import cn.net.autocode.platform.file.service.FileHandle;
import cn.net.autocode.platform.table.cache.DataBaseCache;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import cn.net.autocode.dbManager.SqlWrapper;
import cn.net.autocode.dbManager.SqlWrapperBuilder;
import cn.net.autocode.dbManager.handler.PreparedStatementHandler;
import cn.net.autocode.core.bean.ResultT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("autocode/delProvider")
@Slf4j
public class DelProviderCtrl extends ProviderCtrl{


    private final DataBaseCache dataBaseCache;

    private final SpringProfileConfig springProfileConfig;

    public DelProviderCtrl(DataBaseCache dataBaseCache, SpringProfileConfig springProfileConfig) {
        this.dataBaseCache = dataBaseCache;
        this.springProfileConfig = springProfileConfig;
    }


    @RequestMapping("{tableCode}")
    @Transactional
    public ResultT execute(@PathVariable("tableCode") String tableCode, @RequestBody JSONObject data) throws PlatformQueryException {
        if(data.isEmpty()){
            return ResultT.fail("传入参数为空");
        }

        if(StrUtil.isBlank(data.getString("id"))){//更新操作
            return ResultT.fail("缺失ID值");
        }

        Object idValue = data.get("id");
        List<String> idList=new ArrayList<>();
        if(idValue instanceof JSONArray idArray){
            for (Object id : idArray) {
                if (id instanceof JSONObject idObject) {
                    idList.add(idObject.getString("id"));
                } else {
                    idList.add(id.toString());
                }
            }
        }if(idValue instanceof List idArray){
            for (Object id : idArray) {
                if (id instanceof JSONObject idObject) {
                    idList.add(idObject.getString("id"));
                } else {
                    idList.add(id.toString());
                }
            }
        }else{
            idList.add(idValue.toString());
        }
        //前置脚本
        JSONObject table = this.tableMsg(tableCode);
        String tableName = table.getString("tableName");

        /*
          禁止删除规则判定
         */
        JSONArray rules = dictDao.queryJSONArray("select t2.*,t1.remarks from ac_table_fields t1,ac_table_rules t2 where t1.table_id=t2.table_id and t1.name=t2.field_name and t2.rule_type in (21) and t2.table_id=?", table.getString("id"));
        Map<String,JSONObject> limitValues = new HashMap<>();
        if(rules.size()>0){
            SqlWrapperBuilder swb = new SqlWrapperBuilder(tableName);
            String column = "";
            for(int i=0;i<rules.size();i++){
                rules.getJSONObject(i);
                JSONObject json = rules.getJSONObject(i);
                column=column+","+json.getString("fieldName");
                String fieldName = PreparedStatementHandler.columnToProperty(json.getString("fieldName"));
                if(json.getString("defaultValue")!=null && !json.getString("defaultValue").isBlank()){
                    if(json.getString("remarks")==null || json.getString("remarks").isBlank()){
                        json.put("remarks",fieldName);
                    }
                    limitValues.put(fieldName, json);
                }

            }
            swb.selectColumn(column.substring(1));
            swb.in("id", idList);
            SqlWrapper sqlWrapper = swb.sqlWrapper();
            JSONArray datas = dao.queryJSONArray(sqlWrapper.getSql(),sqlWrapper.getParams().toArray());
            for(int i=0;i<datas.size();i++){
                JSONObject dataJson=datas.getJSONObject(i);
                for(Map.Entry<String,JSONObject> entry:limitValues.entrySet()){
                    if(entry.getValue().getString("defaultValue").equals(dataJson.getString(entry.getKey()))){
                        return ResultT.fail("【"+entry.getValue().getString("remarks")+"】为"+entry.getValue().getString("defaultValue")+"的数据，禁止删除！");
                    }
                }
            }
        }

        /*
          关联表操作
         */
        String message = this.rule2(idList,tableName,table.getString("id"));
        if(StrUtil.isNotBlank(message)){
            return ResultT.fail(message);
        }

        //级联删除sql脚本
        Map<String,JSONArray> fkTableMaps = this.refTables(table.getString("id"),"Y");

        List<String> ids = null;

        if(fkTableMaps.containsKey(tableName)){
            String selectSql = "select fkTable.id from "+tableName +" fkTable,"+tableName+" pkTable where pkTable.id in (?) ";
            selectSql = this.getString(fkTableMaps.get(tableName),selectSql);
            ids = dao.queryListValue(selectSql,String.class,idList);
            idList.addAll(ids);
        }

        Map<String,String> deleteSqlMap = this.rule3(tableName,fkTableMaps);
        if(deleteSqlMap.size()>0){
            for(Map.Entry<String,String> entry:deleteSqlMap.entrySet()){
                try {
                    dao.executeUpdate(entry.getValue(),idList);
                } catch (Exception e) {
                    String fkTableName = entry.getKey();
                    String remark = dataBaseCache.getTableRemark(fkTableName);
                    throw new RuntimeException("【"+remark+"】存在不能级联删除的关联表数据，请先删除【"+remark+"】的关联表数据！");
                }
            }
        }

        if(ids!=null && !ids.isEmpty()){
            dao.executeUpdate("delete from "+tableName+" where id in (?)",ids);
        }

        dao.executeUpdate("delete from "+tableName+" where id in (?)",idList);

        //获取所有的fileId
        JSONArray files = dao.queryJSONArray("select * from autocode_file where table_name=? and busi_id in (?)",tableName,idList);
        for(int i=0;i<files.size();i++){
            JSONObject file = files.getJSONObject(i);
            String storage = file.getString("storage");
            String fileId = file.getString("id");
            if(!"database".equalsIgnoreCase(storage)){
                String filePath = file.getString("filePath");
                try {
                    FileHandle.deleteFromDisk(springProfileConfig.getRootDir(), filePath);
                } catch (IOException e) {
                    //throw new RuntimeException(e);
                }
                dao.executeUpdate("delete from autocode_file where id=?",fileId);
            }else{
                dao.delFile(fileId);
            }
        }
        //后置脚本
        return ResultT.success();
    }


    /**
     * 查询非级联删除的数据
     */
    private String rule2(List<String> idList,String tableName,String tableId){

        Map<String,JSONArray> fkTableMaps = this.refTables(tableId,"N");

        Set<Map.Entry<String, JSONArray>> entrySet = fkTableMaps.entrySet();
        for(Map.Entry<String, JSONArray> entry:entrySet){
            String fkTable = entry.getKey();
            String sql= "select count(1) from "+fkTable+" fkTable," +tableName+" pkTable where pkTable.id in (?) ";
            sql = getString(entry.getValue(), sql);
            int size = dao.queryValue(sql,Integer.class,idList);
            if(size>0){
                return fkTable+"表中存在关联数据，请先删除关联表数据";
            }
        }
        return null;
    }

    /**
     * 级联删除的sql
     */
    private Map<String,String> rule3(String tableName, Map<String,JSONArray> fkTableMaps){
        Map<String,String> deleteSqlMap = new HashMap<>();
        Set<Map.Entry<String, JSONArray>> entrySet = fkTableMaps.entrySet();
        for(Map.Entry<String, JSONArray> entry:entrySet){
            String fkTable = entry.getKey();
            if (!fkTable.equals(tableName)){
                String sql = "delete from "+fkTable+" fkTable where exists(select 1 from " +tableName+" pkTable where pkTable.id in (?) ";
                sql = getString(entry.getValue(), sql);
                sql=sql+")";
                deleteSqlMap.put(fkTable,sql);
            }
        }
        return deleteSqlMap;
    }

    private String getString(JSONArray array, String sql) {
        int columnSize = array.size();
        for(int i=0;i<columnSize;i++){
            JSONObject json = array.getJSONObject(i);
            sql = sql+" and fkTable."+json.getString("fkField")+"=pkTable."+json.getString("pkField");
        }
        return sql;
    }

}
